/**
 * @XMLConfig.as
 *
 * @author sodaChen mail:asframe#163.com
 * @version 1.0
 * <br>Copyright (C), 2012 ASFrame.com
 * <br>This program is protected by copyright laws.
 * <br>Program Name:ASFrame
 * <br>Date:2012-2-20
 */
package com.asframe.conf
{
	import com.asframe.pattern.Singleton;
	import com.asframe.ref.RefConts;
	import com.asframe.ref.Type;
	import com.asframe.ref.Variable;
	import com.asframe.utils.ClassUtils;
	import com.asframe.utils.RefUtils;

	import flash.system.ApplicationDomain;

	/**
	 * XML配置文件的解析和自动填充对象
	 * @author sodaChen
	 * Date:2012-2-21
	 */
	public class XMLConfig extends Singleton
	{
		private static var instance:XMLConfig;
		/**
		 * 获取实例的静态方法实例
		 * @return
		 *
		 */
		public static function getInstance():XMLConfig
		{
			if(instance == null)
			{
				instance = new XMLConfig();
			}
			return instance;
		}

		public function xmlToObject(config:*,target:*):*
		{
			var xml:XML = null;
			if(config is XML)
				xml = config;
			else
				xml = XML(config);

			var paramTagetNull:Boolean = target == null;
			xmlNode(target,xml);
			return target;
		}
		/**
		 * 一个节点的处理
		 */
		private function xmlNode(obj:*,tempXML:XML):void
		{
			//节点的所有属性
			var type:Type = Type.forInstance(obj);
			var xmlList:XMLList = tempXML.attributes();
			//有属性，每个属性都是xml文件，进行填充
			if(xmlList.length() > 0)
				fillAttribute(obj,xmlList);
			//处理children
			var childrenList:XMLList = tempXML.children();
			for each(var xml:XML in childrenList)
			{
				var name:String = xml.name();
				var variable:Variable = type.getVariable(name);
				var typeValue:String = variable.type;
				if(typeValue.indexOf("__AS3__.vec.Vector") != -1)
				{
					//数组和对象需要额外处理,查看是否有类型
					var tempAry:Array = typeValue.split("<");
					var propertyType:String = "";
					if(tempAry.length > 1)
					{
						tempAry = tempAry[1].split(">");
						propertyType = tempAry[0];
					}
					var vectors:* = obj[name];
					if(vectors == null)
					{
						vectors = RefUtils.refObject(typeValue);
						obj[name] = vectors;
					}
					//从这里已经可以确定，这里处理的都是数组，所以得按照处理数组的方式进行
					fillArrays(vectors,xml.children(),propertyType);
				}
				else
				{
					//查看节点是否为数组
					attributeValue(obj,name,typeValue,type,xml);
				}
			}
		}
		private function fillArrays(container:*,xmlList:XMLList,valueClass:String):void
		{
			var value:* = null;
			var clazz:Class = ClassUtils.forName(valueClass);
			for each (var xml:XML in xmlList)
			{
				//增加处理纯string、和数值的情况
				if(valueClass == RefConts.STRING_TYPE || valueClass == RefConts.EMPTY_TYPE)
				{
					container.push(xml.toString());
				}
				else if(valueClass == RefConts.INT_TYPE || valueClass == RefConts.UINT_TYPE || valueClass == RefConts.NUMBER_TYPE)
				{
					//基本数值类型
					container.push(clazz(xml.toString()));
				}
				else if(valueClass == RefConts.BOOLEAN_TYPE)
				{
					if(xml.toString()== "true")
					{
						container.push(true);
					}
					else
					{
						container.push(false);
					}
				}
				else
				{
//					value = RefUtils.refObject(valueClass);
					value = new clazz();
					container.push(value);
					xmlNode(value,xml);
				}
			}
		}
		/**
		 * 根据XMLList的内容填充具体的数据
		 * @param obj:
		 * @param propertys:
		 *
		 */
		private function fillAttribute(obj:*,attributes:XMLList):void
		{
			for each(var xml:XML in attributes)
			{
				//属性不会有数组，单纯的key和value
//				trace("xml.toString():" + xml.toString() + "]");
				if(xml.toString() == "true")
				{
					obj[xml.name().toString()] = true;
				}
				else if(xml.toString() == "false")
				{
					obj[xml.name().toString()] = false;
				}
				else
				{
					obj[xml.name().toString()] = xml;
				}
			}
		}
		private function attributeValue(obj:*,name:String,typeValue:String,type:Type,xml:XML):void
		{
			if(typeValue == RefConts.STRING_TYPE || typeValue == RefConts.EMPTY_TYPE)
			{
				obj[name] = getXMLValue(xml);
			}
			else if(typeValue == RefConts.INT_TYPE || typeValue == RefConts.UINT_TYPE || typeValue == RefConts.NUMBER_TYPE)
			{
				//基本数据类型
				var numValue:String =xml.@value.toString();
				if(numValue == "")
				{
					numValue = xml.toString();
					obj[name] = RefUtils.valueByType(name,numValue,type);;
				}
				else
				{
					obj[name] = xml.@value;
				}
			}
			else if(typeValue == RefConts.BOOLEAN_TYPE)
			{
				if(getXMLValue(xml) == "true")
				{
					obj[name] = true;
				}
				else
				{
					obj[name] = false;
				}
			}
			else
			{
				var typeVariable:Variable = type.getVariable(name);
				if(typeVariable != null)
				{
					typeValue = type.getVariable(name).type;
				}
				else
				{
					typeValue = xml.@type;
				}
				//对象
				var tempObj:* = RefUtils.refObject(typeValue,null);
				obj[name] = tempObj;
				xmlNode(tempObj,xml);
			}
		}
		private function getXMLValue(xml:XML):String
		{
			var value:String = xml.@value.toString();
			if(value == "")
			{
				value = xml.toString();
			}
			return value;
		}
		private function initTargetClass(classPath:String,target:*,applicationDomain:ApplicationDomain):Class
		{
			var targetClass:Class = null;
			if(target == null)
			{
				if(classPath != null && classPath != "")
				{
					targetClass = ClassUtils.forName(classPath,applicationDomain);
					target = new targetClass();
				}
				else
				{
					targetClass = ClassUtils.forName("Object",applicationDomain);
				}
			}
			else
			{
				targetClass = ClassUtils.forInstance(target,applicationDomain);
			}
			return targetClass;
		}
	}
}